/* eslint-disable react/prop-types */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Input,
  Table,
  Popover,
  Icon,
  Button,
  DatePicker,
  Empty,
  message,
  Modal,
  Tooltip
} from 'antd';
import _ from 'lodash';
import moment from 'moment';
import cn from 'classnames';
import { bindActionCreators } from 'redux';
import { deleteOneDayDetail, getOneDayList } from '@api/task';
import { connect } from 'react-redux';

import { LEVEL_TEXT, LEVEL_COLOR } from '@util/constants';
import OnedayModal from './components/oneday-detection-modal';
import './index.less';
import { actions as assetManageActions } from '../../asset-manage/reducer';
import PocModal from './components/poc-modal';
import userImg from '@images/user.svg';

const prefixCls = 'oneday-detection';
const Search = Input.Search;
const RangePicker = DatePicker.RangePicker;

class OneDayDetectionContent extends Component {
  constructor(props) {
    super(props);
    const filterString = sessionStorage.getItem('filter_oneDayList');
    let filter = {};
    try {
      filterString && (filter = JSON.parse(filterString));
      if (filter.affected) {
        filter.affected = JSON.parse(filter.affected);
      }
      // eslint-disable-next-line
    } catch (error) { }
    this.state = {
      loading: false,
      location,
      filter,
      sort: {},
      total: 0,
      tableList: [],
      oneDayModalType: '',
      selectedRowKeys: [],
      record: {},
      selectedRows: [],
      pocModalVisible: false,
      pocModalValue: {}
    };
    this.cache = _.get(this.props, 'location.state.cache', '');
  }

  columns = [
    {
      title: '漏洞名称',
      className: 'vul-name',
      dataIndex: 'origin',
      filters: [{ text: '自定义上传', value: 'customize' }, { text: '系统内置', value: 'inner' }],
      filterMultiple: false,
      render: (_, record) => {
        return (
          <a
            className="be-color"
            onClick={() =>
              this.props.history.push(`/vul/oneday-detection/${record._id}`, {
                ...record,
                cache: this.state.filter.search
              })
            }
          >
            {record.name}
            {record.origin === 'customize' && (
              <Tooltip title="用户自定义漏洞">
                <img src={userImg} alt="" height="22px" width="22px" />
              </Tooltip>
            )}
          </a>
        );
      }
    },
    {
      title: 'CVE ID',
      dataIndex: 'cve_id',
      width: '15%',
      render: cveId => cveId || '-'
    },
    {
      title: '漏洞等级',
      dataIndex: 'level',
      width: 120,
      filters: [
        { text: '严重漏洞', value: 'fatal' },
        { text: '高危漏洞', value: 'high' },
        { text: '中危漏洞', value: 'middle' },
        { text: '低危漏洞', value: 'low' }
      ],
      filterMultiple: false,
      render: level => {
        return (
          <span
            style={{
              color: LEVEL_COLOR[level],
              borderColor: LEVEL_COLOR[level],
              border: '1px solid',
              borderRadius: '20px',
              padding: '2px 10px',
              fontSize: '12px',
              whiteSpace: 'nowrap'
            }}
          >
            {LEVEL_TEXT[level]}
          </span>
        );
      }
    },
    {
      title: '真实影响资产',
      width: 140,
      dataIndex: 'real',
      sorter: true,
      render: (v, record) => {
        const real = _.get(record, 'affectedSiteCount.real', 0);
        // const finallyUpdate = _.get(record, 'latest_task_info.finished', '-');
        // const resultCount = _.get(record, 'latest_task_info.result', '-');
        const latestTaskId = _.get(record, 'latest_task_info.task_oid', '');
        const { history } = this.props;
        return (
          <span
            onClick={() => {
              real !== 0 && history.push('/asset-manage');
              this.props.assetManageActions.setState({
                search: `vul="${record.name}"`,
                // 点击搜索强制刷新
                loadAssetListIndex: Date.now(),
                pagaition: {
                  page: 1,
                  pageSize: 10
                }
              });
            }}
            style={{ whiteSpace: 'nowrap' }}
            className="real_influence"
          >
            <span className={cn({ 'be-color': latestTaskId })}>{real}&nbsp;</span>
          </span>
        );
      }
    },
    {
      title: '可能影响资产',
      width: 140,
      dataIndex: 'suspect',
      sorter: true,
      render: (v, record) => {
        const predict = _.get(record, 'affectedSiteCount.suspect', 0);
        const affected = _.get(record, 'affected', '-');
        return (
          <span
            style={{ whiteSpace: 'nowrap', cursor: 'pointer' }}
            onClick={() => this.jumpToAssetByAffected(affected || '-')}
          >
            可能影响&nbsp;{predict}&nbsp;
            <Popover
              content={
                <div>
                  1.您暂时还未针对该1DAY任务下发过检测任务
                  <br />
                  2.由于该漏洞影响组件/标题/操作系统/服务为“{affected || '-'}”。您有&nbsp;
                  {predict}&nbsp;个资产可能会受到该漏洞的影响
                </div>
              }
              title=""
              overlayStyle={{ width: 380 }}
            >
              <Icon type="info-circle" />
            </Popover>
          </span>
        );
      }
    },
    {
      title: '披露时间',
      width: 140,
      dataIndex: 'lanched',
      sorter: true
    },
    {
      title: '创建时间',
      width: 140,
      dataIndex: 'created',
      sorter: true
    },
    {
      title: '操作',
      dataIndex: 'operations',
      width: 140,
      render: (operations, record) => {
        const disabled = record.origin !== 'customize';
        return (
          <div style={{ whiteSpace: 'nowrap' }}>
            {record.poc && (
              <Button
                type="link"
                size="small"
                onClick={this.wrapChangeModalVisible('single', record)}
              >
                检测
              </Button>
            )}
            <Button
              type="link"
              size="small"
              disabled={disabled}
              onClick={() => {
                this.setState({
                  pocModalVisible: true,
                  pocModalValue: record
                });
              }}
            >
              编辑
            </Button>
            <Button
              type="link"
              size="small"
              onClick={() => {
                this.handleDeleteDetail(record._id);
              }}
              disabled={disabled}
              style={disabled ? {} : { color: '#ff0000' }}
            >
              删除
            </Button>
          </div>
        );
      }
    }
  ];

  handleDeleteDetail = _id => {
    if (!_id) {
      return;
    }
    Modal.confirm({
      content: '确认删除？',
      okText: '确认',
      cancelText: '取消',
      onOk: () => {
        deleteOneDayDetail(_id)
          .then(res => {
            if (_.get(res, 'data.data.result', '') === 'ok') {
              message.success('成功删除POC');
              this.getOneDayList();
            } else {
              message.error('删除失败');
            }
          })
          .catch(err => {
            if (err.message === 'is used') {
              message.error('有正在使用该条漏洞情报的任务');
              return;
            }
            if (err.message === 'is not customize') {
              message.error('只能删除手动添加的漏洞情报');
              return;
            }
            message.error('删除失败');
          });
      }
    });
  };

  handleGetList = () => {
    if (this.cache) {
      const { filter } = this.state;
      filter.search = this.cache;
      this.setState({ filter });
    }
    this.getOneDayList();
  };

  componentDidMount () {
    this.handleGetList();
  }

  componentDidUpdate (prevProps) {
    if (prevProps.location.search !== location.search && !this.cache) {
      const params = new URLSearchParams(location.search);
      if (params.get('query')) {
        this.cache = params.get('query');
      }
      this.handleGetList();
    }
  }


  //获取1DAY漏洞插件列表
  getOneDayList = () => {
    const { filter = {}, sort = {} } = this.state;
    this.setState({ loading: true });
    getOneDayList({ ...filter, ...sort })
      .then(res => {
        const data = _.get(res, 'data.data');
        this.setState({
          loading: false,
          tableList: _.get(data, 'list', []),
          total: _.get(data, 'count', 0)
        });
      })
      .catch(() => this.setState({ loading: false }));
    sessionStorage.setItem('filter_oneDayList', JSON.stringify(filter));
  };

  onSearchChange = e => {
    const { filter } = this.state;
    filter.search = e.target.value;
    this.setState({ filter });
  };

  onTableChange = (pagination, filters, sorter) => {
    document.getElementsByClassName('ant-layout-content')[0].scrollTop = 0;
    let { filter } = this.state;
    const { current, pageSize } = pagination;

    const sort = {};
    if (!_.isEmpty(sorter)) {
      sort[sorter.field] = sorter.order === 'descend' ? 'down' : 'up';
    }

    filter = _.omit(filter, ['created', 'lanched']);
    filter = {
      ...filter,
      page: current,
      pageSize,
      origin: _.get(filters, 'origin[0]'),
      level: _.get(filters, 'level[0]'),
      poc: _.get(filters, 'poc', [])
    };

    this.setState({ filter, sort }, this.getOneDayList);
  };

  wrapChangeModalVisible = (type, record) => visible => {
    this.setState({
      oneDayModalType: visible ? type : '',
      record: record
    });
  };

  jumpToAssetByAffected = affected => {
    const { assetManageActions } = this.props;
    const affectKeys = ['component', 'service', 'os', 'title'];
    assetManageActions.resetQuery({
      search: affectKeys.map(key => `${key}="${affected}"`).join(' || ')
    });
    this.props.history.push('/asset-manage');
  };

  render () {
    const {
      loading,
      total,
      filter,
      tableList,
      oneDayModalType,
      selectedRowKeys,
      record,
      selectedRows,
      pocModalVisible,
      pocModalValue
    } = this.state;
    const pagination = {
      total: total,
      current: filter.page,
      pageSize: filter.pageSize,
      showQuickJumper: true,
      pageSizeOptions: ['10', '20', '50', '100'],
      showSizeChanger: true,
      showTotal: num => `共 ${num} 条`,
      size: 'small'
    };

    const rowSelection = {
      onChange: (keys = [], rows = []) => {
        const { selectedRows } = this.state;
        const lastSelectedRows = selectedRows.filter(row => keys.includes(row._id));
        const uniqSelectedRows = _.uniqBy(rows.concat(lastSelectedRows), '_id');
        this.setState({
          selectedRows: uniqSelectedRows,
          selectedRowKeys: keys
        });
      },
      selectedRowKeys,
      getCheckboxProps: record => ({
        disabled: !record.poc
      })
    };

    const disabled = selectedRowKeys.length === 0;
    return (
      <div className={`${prefixCls}`}>
        <div className={`${prefixCls}-title`}>
          <span className="text">漏洞情报</span>
        </div>
        <div className={`${prefixCls}-header`}>
          <div className={`${prefixCls}-header-left`}>
            <Button
              type="primary"
              disabled={disabled}
              onClick={this.wrapChangeModalVisible('batch')}
            >
              批量下发检测
            </Button>
            披露时间：
            <RangePicker
              style={{ width: '230px' }}
              onChange={(data, dataStr) => {
                filter.lanchedStart = dataStr[0];
                filter.lanchedEnd = dataStr[1];
                filter.page = 1;
                this.setState({ filter }, this.getOneDayList);
              }}
              defaultValue={
                filter.lanchedStart ? [moment(filter.lanchedStart), moment(filter.lanchedEnd)] : []
              }
            />
          </div>
          <div className={cn(`${prefixCls}-header-right`)}>
            <Search
              enterButton
              placeholder="请输入漏洞名称或CVE ID"
              onSearch={value => {
                filter.search = value.toString();
                filter.page = 1;
                this.setState({ filter }, this.getOneDayList);
              }}
              onChange={this.onSearchChange}
              value={filter.search}
            />
          </div>
        </div>
        <div className={`${prefixCls}-header-config`}>
          <Button onClick={() => this.setState({ pocModalVisible: true })} type="primary">
            上传POC
          </Button>
        </div>
        <div className={`${prefixCls}-header-count`}>共有“{total}”个漏洞情报</div>
        <Table
          rowKey="_id"
          loading={{ spinning: loading, tip: '加载中' }}
          locale={{
            emptyText: (
              <Empty
                description={loading ? ' ' : '暂无数据'}
                image={Empty.PRESENTED_IMAGE_SIMPLE}
              />
            )
          }}
          rowClassName={record => {
            let predict = _.get(record, 'affectedSiteCount.suspect', 0);
            let real = _.get(record, 'affectedSiteCount.real', 0);
            return predict || real ? 'has-affected' : 'no-affected';
          }}
          columns={this.columns}
          pagination={pagination}
          dataSource={tableList}
          rowSelection={rowSelection}
          onChange={this.onTableChange}
        />
        <OnedayModal
          modalVisible={Boolean(oneDayModalType)}
          modalType={oneDayModalType}
          changeModalVisible={this.wrapChangeModalVisible('')}
          onClickSubmit={() => this.setState({ oneDayModalType: false, record: {} })}
          onedays={record ? [record] : selectedRows}
          origin={'site'}
        />
        <PocModal
          onOk={() => {
            this.getOneDayList();
            this.setState({ pocModalVisible: false, pocModalValue: {} });
          }}
          value={pocModalValue}
          visible={pocModalVisible}
          onCancel={() => this.setState({ pocModalVisible: false, pocModalValue: {} })}
        />
      </div>
    );
  }
}

OneDayDetectionContent.propTypes = {
  history: PropTypes.object,
  name: PropTypes.string,
  modules: PropTypes.array,
  assetManageActions: PropTypes.object
};

const mapStateToProps = state => {
  return {
    modules: _.get(state, 'auth.cert.modules', [])
  };
};

const mapDispatchToProps = dispatch => {
  return {
    assetManageActions: bindActionCreators(assetManageActions, dispatch)
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(OneDayDetectionContent);
